home *** CD-ROM | disk | FTP | other *** search
Wrap
# Source Generated with Decompyle++ # File: in.pyc (Python 2.6) __all__ = ('tabengine',) import os import ibus from ibus import keysyms from ibus import modifier from ibus import ascii import tabdict import re patt_edit = re.compile('(.*)###(.*)###(.*)') patt_uncommit = re.compile('(.*)@@@(.*)') from gettext import dgettext _ = lambda a: dgettext('ibus-table', a) N_ = lambda a: a import dbus class KeyEvent: def __init__(self, keyval, is_press, state): self.code = keyval self.mask = state if not is_press: self.mask |= modifier.RELEASE_MASK def __str__(self): return '%s 0x%08x' % (keysyms.keycode_to_name(self.code), self.mask) class editor(object): '''Hold user inputs chars and preedit string''' def __init__(self, phrase_table_index, valid_input_chars, max_key_length, database, parser = tabdict.parse, deparser = tabdict.deparse, max_length = 64): self.db = database self._pt = phrase_table_index self._parser = parser self._deparser = deparser self._max_key_len = int(max_key_length) self._max_length = max_length self._valid_input_chars = valid_input_chars self._chars = [ [], [], []] self._t_chars = [] self._u_chars = [] self._tabkey_list = [] self._strings = [] self._cursor = [ 0, 0] self._candidates = [ [], []] self._lookup_table = ibus.LookupTable(tabengine._page_size) self._py_mode = False self._zi = u'' self._caret = 0 self._onechar = False self._chinese_mode = self.get_chinese_mode() def get_chinese_mode(self): '''Use LC_CTYPE in your box to determine the _chinese_mode''' try: if os.environ.has_key('LC_CTYPE'): _editor__lc = os.environ['LC_CTYPE'].split('.')[0].lower() else: _editor__lc = os.environ['LANG'].split('.')[0].lower() if _editor__lc.find('zh_') == 0: _editor__place = _editor__lc.split('_')[1] if _editor__place == 'cn': return 0 return 1 _editor__lc.find('zh_') == 0 if self.db._is_chinese(): return 0 return -1 except: return -1 def change_chinese_mode(self): if self._chinese_mode != -1: self._chinese_mode = (self._chinese_mode + 1) % 5 def clear(self): '''Remove data holded''' self.over_input() self._t_chars = [] self._strings = [] self._cursor = [ 0, 0] self._py_mode = False self._zi = u'' self.update_candidates def is_empty(self): return len(self._t_chars) == 0 def clear_input(self): ''' Remove input characters held for Table mode, ''' self._chars = [ [], [], []] self._tabkey_list = [] self._lookup_table.clean() self._lookup_table.show_cursor(False) self._candidates = [ [], []] def over_input(self): ''' Remove input characters held for Table mode, ''' self.clear_input() self._u_chars = [] def set_parser(self, parser): '''change input parser''' self.clear() self._parser = parser def add_input(self, c): '''add input character''' if len(self._t_chars) == self._max_length: return True self._zi = u'' if self._cursor[1]: self.split_phrase() if (len(self._chars[0]) == self._max_key_len or not (self._py_mode) or len(self._chars[0]) == 7) and self._py_mode: self.auto_commit_to_preedit() res = self.add_input(c) return res if self._chars[1]: self._chars[1].append(c) elif (not (self._py_mode) or c in self._valid_input_chars or self._py_mode) and c in u'abcdefghijklmnopqrstuvwxyz!@#$%': try: self._tabkey_list += self._parser(c) self._chars[0].append(c) self._chars[1].append(c) else: self._chars[1].append(c) self._t_chars.append(c) res = self.update_candidates() return res def pop_input(self): '''remove and display last input char held''' _c = '' if self._chars[1]: _c = self._chars[1].pop() elif self._chars[0]: _c = self._chars[0].pop() self._tabkey_list.pop() if not self._chars[0] and self._u_chars: self._chars[0] = self._u_chars.pop() self._chars[1] = self._chars[1][:-1] self._tabkey_list = self._parser(self._chars[0]) self._strings.pop(self._cursor[0] - 1) self._cursor[0] -= 1 self._t_chars.pop() self.update_candidates() return _c def get_input_chars(self): '''get characters held, valid and invalid''' return self._chars[0] + self._chars[1] def get_input_chars_string(self): '''Get valid input char string''' return u''.join(map(str, self._t_chars)) def get_all_input_strings(self): '''Get all uncommit input characters, used in English mode or direct commit''' return u''.join(map(u''.join, self._u_chars + [ self._chars[0]] + [ self._chars[1]])) def get_index(self, key): '''Get the index of key in database table''' return self._pt.index(key) def split_phrase(self): '''Splite current phrase into two phrase''' _head = u'' _end = u'' try: _head = self._strings[self._cursor[0]][:self._cursor[1]] _end = self._strings[self._cursor[0]][self._cursor[1]:] self._strings.pop(self._cursor[0]) self._strings.insert(self._cursor[0], _head) self._strings.insert(self._cursor[0] + 1, _end) self._cursor[0] += 1 self._cursor[1] = 0 except: pass def remove_before_string(self): '''Remove string before cursor''' if self._cursor[1] != 0: self.split_phrase() if self._cursor[0] > 0: self._strings.pop(self._cursor[0] - 1) self._cursor[0] -= 1 if self._cursor == [ 0, 0]: self._t_chars = [] def remove_after_string(self): '''Remove string after cursor''' if self._cursor[1] != 0: self.split_phrase() if self._cursor[0] >= len(self._strings): pass else: self._strings.pop(self._cursor[0]) def remove_before_char(self): '''Remove character before cursor''' if self._cursor[1] > 0: _str = self._strings[self._cursor[0]] self._strings[self._cursor[0]] = _str[:self._cursor[1] - 1] + _str[self._cursor[1]:] self._cursor[1] -= 1 elif self._cursor[0] == 0: pass elif len(self._strings[self._cursor[0] - 1]) == 1: self.remove_before_string() else: self._strings[self._cursor[0] - 1] = self._strings[self._cursor[0] - 1][:-1] if self._cursor == [ 0, 0]: self._t_chars = [] def remove_after_char(self): '''Remove character after cursor''' if self._cursor[1] == 0: if self._cursor[0] == len(self._strings): pass elif len(self._strings[self._cursor[0]]) == 1: self.remove_after_string() else: self._strings[self._cursor[0]] = self._strings[self._cursor[0]][1:] elif self._cursor[1] + 1 == len(self._strings[self._cursor[0]]): self.split_phrase() self.remove_after_string() else: string = self._strings[self._cursor[0]] self._strings[self._cursor[0]] = string[:self._cursor[1]] + string[self._cursor[1] + 1:] def get_invalid_input_chars(self): '''get invalid characters held''' return self._chars[1] def get_invalid_input_string(self): '''get invalid characters in string form''' return u''.join(self._chars[1]) def get_preedit_strings(self): '''Get preedit strings''' if self._candidates[0]: if self._py_mode: _p_index = 8 else: _p_index = self.get_index('phrase') _candi = u'###' + self._candidates[0][int(self._lookup_table.get_cursor_pos())][_p_index] + u'###' else: input_chars = self.get_input_chars() if input_chars: _candi = u''.join([ '###'] + map(str, input_chars) + [ '###']) else: _candi = u'' if self._strings: res = u'' _cursor = self._cursor[0] _luc = len(self._u_chars) if _luc: if not _candi == u'' or u'######': pass _candi = _candi res = u''.join(self._strings[:_cursor - _luc] + [ u'@@@'] + self._strings[_cursor - _luc:_cursor] + [ _candi] + self._strings[_cursor:]) else: res = u''.join(self._strings[:_cursor] + [ _candi] + self._strings[_cursor:]) return res return _candi def add_caret(self, addstr): '''add length to caret position''' self._caret += len(addstr) def get_caret(self): '''Get caret position in preedit strings''' self._caret = 0 if self._cursor[0] and self._strings: map(self.add_caret, self._strings[:self._cursor[0]]) self._caret += self._cursor[1] self._caret += len(_candi) return self._caret def arrow_left(self): '''Process Arrow Left Key Event. Update cursor data when move caret left''' if self.get_preedit_strings(): if not self.get_input_chars() or self._u_chars: if self._cursor[1] > 0: self._cursor[1] -= 1 elif self._cursor[0] > 0: self._cursor[1] = len(self._strings[self._cursor[0] - 1]) - 1 self._cursor[0] -= 1 else: self._cursor[0] = len(self._strings) self._cursor[1] = 0 self.update_candidates() return True return False def arrow_right(self): '''Process Arrow Right Key Event. Update cursor data when move caret right''' if self.get_preedit_strings(): if not self.get_input_chars() or self._u_chars: if self._cursor[1] == 0: if self._cursor[0] == len(self._strings): self._cursor[0] = 0 else: self._cursor[1] += 1 else: self._cursor[1] += 1 if self._cursor[1] == len(self._strings[self._cursor[0]]): self._cursor[0] += 1 self._cursor[1] = 0 self.update_candidates() return True return False def control_arrow_left(self): '''Process Control + Arrow Left Key Event. Update cursor data when move caret to string left''' if self.get_preedit_strings(): if not self.get_input_chars() or self._u_chars: if self._cursor[1] == 0: if self._cursor[0] == 0: self._cursor[0] = len(self._strings) - 1 else: self._cursor[0] -= 1 else: self._cursor[1] = 0 self.update_candidates() return True return False def control_arrow_right(self): '''Process Control + Arrow Right Key Event. Update cursor data when move caret to string right''' if self.get_preedit_strings(): if not self.get_input_chars() or self._u_chars: if self._cursor[1] == 0: if self._cursor[0] == len(self._strings): self._cursor[0] = 1 else: self._cursor[0] += 1 else: self._cursor[0] += 1 self._cursor[1] = 0 self.update_candidates() return True return False def ap_candidate(self, candi): '''append candidate to lookup_table''' if not self._py_mode: _p_index = self.get_index('phrase') _fkey = self.get_index('m0') else: _p_index = 8 _fkey = 1 if self.db._is_chinese: _tbks = u''.join(map(self._deparser, candi[_fkey + len(self._tabkey_list):_p_index - 1])) if self._py_mode: _tbks = _tbks.replace('!', '\xe2\x86\x911').replace('@', '\xe2\x86\x912').replace('#', '\xe2\x86\x913').replace('$', '\xe2\x86\x914').replace('%', '\xe2\x86\x915') else: _tbks = u''.join(map(self._deparser, candi[_fkey + len(self._tabkey_list):_p_index])) _phrase = candi[_p_index] attrs = ibus.AttrList() attrs.append(ibus.AttributeForeground(1668002, 0, len(_phrase) + len(_tbks))) if candi[-2] < 0: attrs.append(ibus.AttributeForeground(7798979, 0, len(_phrase))) elif candi[-1] > 0: attrs.append(ibus.AttributeForeground(0, 0, len(_phrase))) else: attrs.append(ibus.AttributeForeground(0, 0, len(_phrase))) self._lookup_table.append_candidate(ibus.Text(_phrase + _tbks, attrs)) self._lookup_table.show_cursor(False) def filter_candidates(self, candidates): '''Filter candidates if IME is Chinese''' if self._chinese_mode not in (2, 3): return candidates[:] bm_index = self._pt.index('category') if self._chinese_mode == 2: return (filter,)((lambda x: x[bm_index] & 1), candidates) + (filter,)((lambda x: if x[bm_index] & 2: passnot (x[bm_index] & 1)), candidates) + (filter,)((lambda x: x[bm_index] & 4), candidates) if self._chinese_mode == 3: return (filter,)((lambda x: x[bm_index] & 2), candidates) + (filter,)((lambda x: if x[bm_index] & 1: passnot (x[bm_index] & 2)), candidates) + (filter,)((lambda x: x[bm_index] & 4), candidates) def update_candidates(self): '''Update lookuptable''' if self._chars[0] == self._chars[2] or self._candidates[0] or self._chars[1]: pass else: only_one_last = self.one_candidate() self._lookup_table.clean() self._lookup_table.show_cursor(False) if self._tabkey_list: if not self._py_mode: if self.db._is_chinese: bm_index = self._pt.index('category') if self._chinese_mode == 0: self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar, 1) elif self._chinese_mode == 1: self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar, 2) else: self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar) else: self._candidates[0] = self.db.select_words(self._tabkey_list, self._onechar) else: self._candidates[0] = self.db.select_zi(self._tabkey_list) self._chars[2] = self._chars[0][:] else: self._candidates[0] = [] if self._candidates[0]: self._candidates[0] = self.filter_candidates(self._candidates[0]) if self._candidates[0]: map(self.ap_candidate, self._candidates[0]) elif self._chars[0]: if not self._chars[1]: if ascii.ispunct(self._chars[0][-1].encode('ascii')) and len(self._chars[0][:-1]) in self.db.pkeylens or only_one_last: if self._py_mode: if self._chars[0][-1] in '!@#$%': self._chars[0].pop() self._tabkey_list.pop() return True if self._candidates[1]: self._candidates[0] = self._candidates[1] self._candidates[1] = [] last_input = self.pop_input() self.auto_commit_to_preedit() res = self.add_input(last_input) return res self.pop_input() self._lookup_table.clean() self._lookup_table.show_cursor(False) return False only_one_last self._chars[1].append(self._chars[0].pop()) self._tabkey_list.pop() self._candidates[0] = [] else: self._lookup_table.clean() self._lookup_table.show_cursor(False) self._candidates[1] = self._candidates[0] return True def commit_to_preedit(self): '''Add select phrase in lookup table to preedit string''' if not self._py_mode: _p_index = self.get_index('phrase') else: _p_index = 8 try: self._strings.insert(self._cursor[0], self._candidates[0][self.get_cursor_pos()][_p_index]) self._cursor[0] += 1 if self._py_mode: self._zi = self._candidates[0][self.get_cursor_pos()][_p_index] self.over_input() self.update_candidates() except: pass def auto_commit_to_preedit(self): '''Add select phrase in lookup table to preedit string''' if not self._py_mode: _p_index = self.get_index('phrase') else: _p_index = 8 try: self._u_chars.append(self._chars[0][:]) self._strings.insert(self._cursor[0], self._candidates[0][self.get_cursor_pos()][_p_index]) self._cursor[0] += 1 self.clear_input() self.update_candidates() except: pass def get_aux_strings(self): '''Get aux strings''' input_chars = self.get_input_chars() if input_chars: aux_string = u''.join(self._chars[0]) if self._py_mode: aux_string = aux_string.replace('!', '1').replace('@', '2').replace('#', '3').replace('$', '4').replace('%', '5') return aux_string aux_string = u'' if self._zi: tabcodes = self.db.find_zi_code(self._zi) aux_string = self._zi + u': ' aux_string = u' '.join(tabcodes) cstr = u''.join(self._strings) if self.db.user_can_define_phrase: if len(cstr) > 1: aux_string += u'\t#: ' + self.db.parse_phrase_to_tabkeys(cstr) return aux_string def arrow_down(self): '''Process Arrow Down Key Event Move Lookup Table cursor down''' res = self._lookup_table.cursor_down() self.update_candidates() if not res and self._candidates[0]: return True return res def arrow_up(self): '''Process Arrow Up Key Event Move Lookup Table cursor up''' res = self._lookup_table.cursor_up() self.update_candidates() if not res and self._candidates[0]: return True return res def page_down(self): '''Process Page Down Key Event Move Lookup Table page down''' res = self._lookup_table.page_down() self.update_candidates() if not res and self._candidates[0]: return True return res def page_up(self): '''Process Page Up Key Event move Lookup Table page up''' res = self._lookup_table.page_up() self.update_candidates() if not res and self._candidates[0]: return True return res def number(self, index): '''Select the candidates in Lookup Table index should start from 0''' self._lookup_table.set_cursor_pos_in_current_page(index) if index != self._lookup_table.get_cursor_pos_in_current_page(): return False self.commit_to_preedit() return True def alt_number(self, index): '''Remove the candidates in Lookup Table from user_db index should start from 0''' cps = self._lookup_table.get_current_page_start() pos = cps + index if len(self._candidates[0]) > pos: can = self._candidates[0][pos] if can[-2] < 0: self.db.remove_phrase(can) self._chars[2].pop() self.update_candidates() return True return False def get_cursor_pos(self): '''get lookup table cursor position''' return self._lookup_table.get_cursor_pos() def get_lookup_table(self): '''Get lookup table''' return self._lookup_table def is_lt_visible(self): '''Check whether lookup table is visible''' return self._lookup_table.is_cursor_visible() def backspace(self): '''Process backspace Key Event''' self._zi = u'' if self.get_input_chars(): self.pop_input() return True if self.get_preedit_strings(): self.remove_before_char() return True return False def control_backspace(self): '''Process control+backspace Key Event''' self._zi = u'' if self.get_input_chars(): self.over_input() return True if self.get_preedit_strings(): self.remove_before_string() return True return False def delete(self): '''Process delete Key Event''' self._zi = u'' if self.get_input_chars(): return True if self.get_preedit_strings(): self.remove_after_char() return True return False def control_delete(self): '''Process control+delete Key Event''' self._zi = u'' if self.get_input_chars(): return True if self.get_preedit_strings(): self.remove_after_string() return True return False def l_shift(self): '''Process Left Shift Key Event as immediately commit to preedit strings''' if self._chars[0]: self.commit_to_preedit() return True return False def r_shift(self): '''Proess Right Shift Key Event as changed between PinYin Mode and Table Mode''' self._zi = u'' if self._chars[0]: self.commit_to_preedit() self._py_mode = not (self._py_mode) return True def space(self): '''Process space Key Event return (KeyProcessResult,whethercommit,commitstring)''' if self._chars[1]: return (False, u'') if self._t_chars: istr = self.get_all_input_strings() self.commit_to_preedit() pstr = self.get_preedit_strings() self.clear() return (True, pstr, istr) return (False, u'', u'') def one_candidate(self): '''Return true if there is only one candidate''' return len(self._candidates[0]) == 1 class tabengine(ibus.EngineBase): '''The IM Engine for Tables''' _page_size = 6 def __init__(self, bus, obj_path, db): super(tabengine, self).__init__(bus, obj_path) self._lookup_table = ibus.LookupTable(tabengine._page_size) self.db = db self._parser = tabdict.parse self._icon_dir = '%s%s%s%s' % (os.getenv('IBUS_TABLE_LOCATION'), os.path.sep, 'icons', os.path.sep) self._mode = 1 self._ime_py = self.db.get_ime_property('pinyin_mode') if self._ime_py: if self._ime_py.lower() == u'true': self._ime_py = True else: self._ime_py = False else: print 'We coult not find "pinyin_mode" entry in database, is it a outdated database?' self._ime_py = False self._status = self.db.get_ime_property('status_prompt').encode('utf8') self._chars = self.db.get_ime_property('valid_input_chars') self._valid_input_chars = [] for _c in self._chars: if _c in tabdict.tab_key_list: self._valid_input_chars.append(_c) continue del self._chars self._pt = self.db.get_phrase_table_index() self._ml = int(self.db.get_ime_property('max_key_length')) self._editor = editor(self._pt, self._valid_input_chars, self._ml, self.db) self._prev_key = None self._prev_char = None self._double_quotation_state = False self._single_quotation_state = False self._full_width_letter = [ False, self.db.get_ime_property('def_full_width_letter').lower() == u'true'] self._full_width_punct = [ False, self.db.get_ime_property('def_full_width_punct').lower() == u'true'] try: self._auto_commit = self.db.get_ime_property('auto_commit').lower() == u'true' except: self._auto_commit = False self._len_list = [ 0] try: bus = dbus.SessionBus() user = os.path.basename(os.path.expanduser('~')) self._sm_bus = bus.get_object('org.ibus.table.SpeedMeter.%s' % user, '/org/ibus/table/SpeedMeter') self._sm = dbus.Interface(self._sm_bus, 'org.ibus.table.SpeedMeter') except: self._sm = None self._sm_on = False self._on = False self.reset() def reset(self): self._editor.clear() self._double_quotation_state = False self._single_quotation_state = False self._prev_key = None self._init_properties() self._update_ui() def do_destroy(self): self.reset() self.focus_out() super(tabengine, self).do_destroy() def _init_properties(self): self.properties = ibus.PropList() self._status_property = ibus.Property(u'status') if self.db._is_chinese: self._cmode_property = ibus.Property(u'cmode') self._letter_property = ibus.Property(u'letter') self._punct_property = ibus.Property(u'punct') self._py_property = ibus.Property(u'py_mode') self._onechar_property = ibus.Property(u'onechar') self._auto_commit_property = ibus.Property(u'acommit') for prop in (self._status_property, self._letter_property, self._punct_property, self._py_property, self._onechar_property, self._auto_commit_property): self.properties.append(prop) if self.db._is_chinese: self.properties.insert(1, self._cmode_property) self.register_properties(self.properties) self._refresh_properties() def _refresh_properties(self): '''Method used to update properties''' if self._mode == 1: if self._status == u'CN': self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'chinese.svg')) self._status_property.set_label(_(u'CN')) else: self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'ibus-table.svg')) self._status_property.set_label(self._status) self._status_property.set_tooltip(_(u'Switch to English mode')) else: self._status_property.set_icon(u'%s%s' % (self._icon_dir, 'english.svg')) self._status_property.set_label(_(u'EN')) self._status_property.set_tooltip(_(u'Switch to Table mode')) if self._full_width_letter[self._mode]: self._letter_property.set_icon(u'%s%s' % (self._icon_dir, 'full-letter.svg')) self._letter_property.set_tooltip(_(u'Switch to half letter')) else: self._letter_property.set_icon(u'%s%s' % (self._icon_dir, 'half-letter.svg')) self._letter_property.set_tooltip(_(u'Switch to full letter')) if self._full_width_punct[self._mode]: self._punct_property.set_icon(u'%s%s' % (self._icon_dir, 'full-punct.svg')) self._punct_property.set_tooltip(_(u'Switch to half punction')) else: self._punct_property.set_icon(u'%s%s' % (self._icon_dir, 'half-punct.svg')) self._punct_property.set_tooltip(_(u'Switch to full punction')) if self._editor._py_mode: self._py_property.set_icon(u'%s%s' % (self._icon_dir, 'py-mode.svg')) self._py_property.set_tooltip(_(u'Switch to Table mode')) else: self._py_property.set_icon(u'%s%s' % (self._icon_dir, 'tab-mode.svg')) self._py_property.set_tooltip(_(u'Switch to PinYin mode')) if self._editor._onechar: self._onechar_property.set_icon(u'%s%s' % (self._icon_dir, 'onechar.svg')) self._onechar_property.set_tooltip(_(u'Switch to phrase mode')) else: self._onechar_property.set_icon(u'%s%s' % (self._icon_dir, 'phrase.svg')) self._onechar_property.set_tooltip(_(u'Switch to single char mode')) if self._auto_commit: self._auto_commit_property.set_icon(u'%s%s' % (self._icon_dir, 'acommit.svg')) self._auto_commit_property.set_tooltip(_(u'Switch to normal commit mode, which use space to commit')) else: self._auto_commit_property.set_icon(u'%s%s' % (self._icon_dir, 'ncommit.svg')) self._auto_commit_property.set_tooltip(_(u'Switch to direct commit mode')) if self.db._is_chinese: if self._editor._chinese_mode == 0: self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'sc-mode.svg')) self._cmode_property.set_tooltip(_(u'Switch to Traditional Chinese mode')) elif self._editor._chinese_mode == 1: self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'tc-mode.svg')) self._cmode_property.set_tooltip(_(u'Switch to Simplify Chinese first Big Charset Mode')) elif self._editor._chinese_mode == 2: self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'scb-mode.svg')) self._cmode_property.set_tooltip(_(u'Switch to Traditional Chinese first Big Charset Mode')) elif self._editor._chinese_mode == 3: self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'tcb-mode.svg')) self._cmode_property.set_tooltip(_(u'Switch to Big Charset Mode')) elif self._editor._chinese_mode == 4: self._cmode_property.set_icon(u'%s%s' % (self._icon_dir, 'cb-mode.svg')) self._cmode_property.set_tooltip(_(u'Switch to Simplify Chinese Mode')) map(self.update_property, self.properties) def _change_mode(self): '''Shift input mode, TAB -> EN -> TAB ''' self._mode = int(not (self._mode)) self.reset() self._update_ui() def property_activate(self, property, prop_state = ibus.PROP_STATE_UNCHECKED): '''Shift property''' if property == u'status': self._change_mode() elif property == u'py_mode' and self._ime_py: self._editor.r_shift() elif property == u'onechar': self._editor._onechar = not (self._editor._onechar) elif property == u'acommit': self._auto_commit = not (self._auto_commit) elif property == u'letter': self._full_width_letter[self._mode] = not self._full_width_letter[self._mode] elif property == u'punct': self._full_width_punct[self._mode] = not self._full_width_punct[self._mode] elif property == u'cmode': self._editor.change_chinese_mode() self.reset() self._refresh_properties() def _update_preedit(self): '''Update Preedit String in UI''' _str = self._editor.get_preedit_strings() if _str == u'': super(tabengine, self).update_preedit_text(ibus.Text(u'', None), 0, False) else: attrs = ibus.AttrList() res = patt_edit.match(_str) if res: _str = u'' ures = patt_uncommit.match(res.group(1)) if ures: _str = u''.join(ures.groups()) lc = len(ures.group(1)) lu = len(ures.group(2)) attrs.append(ibus.AttributeForeground(1785603, 0, lc)) attrs.append(ibus.AttributeForeground(562594, lc, lu)) lg1 = len(_str) else: _str += res.group(1) lg1 = len(res.group(1)) attrs.append(ibus.AttributeForeground(1785603, 0, lg1)) _str += res.group(2) _str += res.group(3) lg2 = len(res.group(2)) lg3 = len(res.group(3)) attrs.append(ibus.AttributeForeground(921248, lg1, lg2)) attrs.append(ibus.AttributeForeground(1785603, lg1 + lg2, lg3)) else: attrs.append(ibus.AttributeForeground(1785603, 0, len(_str))) attrs = ibus.AttrList() attrs.append(ibus.AttributeUnderline(ibus.ATTR_UNDERLINE_SINGLE, 0, len(_str))) super(tabengine, self).update_preedit_text(ibus.Text(_str, attrs), self._editor.get_caret(), True) def _update_aux(self): '''Update Aux String in UI''' _ic = self._editor.get_aux_strings() if _ic: attrs = ibus.AttrList([ ibus.AttributeForeground(9770421, 0, len(_ic))]) super(tabengine, self).update_auxiliary_text(ibus.Text(_ic, attrs), True) else: self.hide_auxiliary_text() def _update_lookup_table(self): '''Update Lookup Table in UI''' if self._editor.is_empty(): self.hide_lookup_table() return None self.update_lookup_table(self._editor.get_lookup_table(), True, True) def _update_ui(self): '''Update User Interface''' self._update_lookup_table() self._update_preedit() self._update_aux() def add_string_len(self, astring): if self._sm_on: try: self._sm.Accumulate(len(astring)) def commit_string(self, string): self._editor.clear() self._update_ui() super(tabengine, self).commit_text(ibus.Text(string)) self._prev_char = string[-1] def _convert_to_full_width(self, c): '''convert half width character to full width''' return ibus.unichar_half_to_full(c) def _match_hotkey(self, key, code, mask): return False def process_key_event(self, keyval, keycode, state): '''Process Key Events Key Events include Key Press and Key Release, modifier means Key Pressed ''' key = KeyEvent(keyval, state & modifier.RELEASE_MASK == 0, state) key.mask &= ~(modifier.MOD2_MASK) result = self._process_key_event(key) self._prev_key = key return result def _process_key_event(self, key): '''Internal method to process key event''' if not (self._editor._t_chars) and self._match_hotkey(key, keysyms.Shift_L, modifier.SHIFT_MASK + modifier.RELEASE_MASK): self._change_mode() return True if self._match_hotkey(key, keysyms.space, modifier.SHIFT_MASK): self.property_activate('letter') return True if self._match_hotkey(key, keysyms.period, modifier.CONTROL_MASK): self.property_activate('punct') return True if self._mode: return self._table_mode_process_key_event(key) return self._english_mode_process_key_event(key) def _english_mode_process_key_event(self, key): '''English Mode Process Key Event''' if key.mask & modifier.RELEASE_MASK: return True if key.code >= 128: return False if key.mask & modifier.CONTROL_MASK + modifier.ALT_MASK: return False c = unichr(key.code) if ascii.ispunct(key.code): if self._full_width_punct[self._mode]: self.commit_string(self._convert_to_full_width(c)) return True self.commit_string(c) return True ascii.ispunct(key.code) if self._full_width_letter[self._mode]: self.commit_string(self._convert_to_full_width(c)) return True self.commit_string(c) return True return False def _table_mode_process_key_event(self, key): '''Xingma Mode Process Key Event''' cond_letter_translate = lambda c: if self._full_width_letter[self._mode]: self._convert_to_full_width(c)c cond_punct_translate = lambda c: if self._full_width_punct[self._mode]: self._convert_to_full_width(c)c if self._match_hotkey(key, keysyms.Shift_R, modifier.SHIFT_MASK + modifier.RELEASE_MASK) and self._ime_py: res = self._editor.r_shift() self._refresh_properties() self._update_ui() return res if self._match_hotkey(key, keysyms.Shift_R, modifier.SHIFT_MASK + modifier.RELEASE_MASK) or self._match_hotkey(key, keysyms.Shift_L, modifier.SHIFT_MASK + modifier.RELEASE_MASK): res = self._editor.l_shift() self._update_ui() return res if self._match_hotkey(key, keysyms.comma, modifier.CONTROL_MASK): self.property_activate(u'onechar') return True if self._match_hotkey(key, keysyms.slash, modifier.CONTROL_MASK): self.property_activate(u'acommit') return True if self._match_hotkey(key, keysyms.semicolon, modifier.CONTROL_MASK): self.property_activate(u'cmode') return True if self._match_hotkey(key, keysyms.apostrophe, modifier.CONTROL_MASK): self._sm_on = not (self._sm_on) return True if key.mask & modifier.RELEASE_MASK: return True if key.code == keysyms.Escape: self.reset() self._update_ui() return True if key.code in (keysyms.Return, keysyms.KP_Enter): commit_string = self._editor.get_all_input_strings() self.commit_string(commit_string) return True if key.code in (keysyms.Down, keysyms.KP_Down): res = self._editor.arrow_down() self._update_ui() return res if key.code in (keysyms.Up, keysyms.KP_Up): res = self._editor.arrow_up() self._update_ui() return res if key.code in (keysyms.Left, keysyms.KP_Left) and key.mask & modifier.CONTROL_MASK: res = self._editor.control_arrow_left() self._update_ui() return res if key.code in (keysyms.Right, keysyms.KP_Right) and key.mask & modifier.CONTROL_MASK: res = self._editor.control_arrow_right() self._update_ui() return res if key.code in (keysyms.Left, keysyms.KP_Left): res = self._editor.arrow_left() self._update_ui() return res if key.code in (keysyms.Right, keysyms.KP_Right): res = self._editor.arrow_right() self._update_ui() return res if key.code == keysyms.BackSpace and key.mask & modifier.CONTROL_MASK: res = self._editor.control_backspace() self._update_ui() return res if key.code == keysyms.BackSpace: res = self._editor.backspace() self._update_ui() return res if key.code == keysyms.Delete and key.mask & modifier.CONTROL_MASK: res = self._editor.control_delete() self._update_ui() return res if key.code == keysyms.Delete: res = self._editor.delete() self._update_ui() return res if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0] and key.mask & modifier.CONTROL_MASK: res = self._editor.number(key.code - keysyms._1) self._update_ui() return res if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0] and key.mask & modifier.ALT_MASK: res = self._editor.alt_number(key.code - keysyms._1) self._update_ui() return res if key.code == keysyms.space: o_py = self._editor._py_mode sp_res = self._editor.space() if sp_res[0]: self.commit_string(sp_res[1]) self.add_string_len(sp_res[1]) self.db.check_phrase(sp_res[1], sp_res[2]) elif sp_res[1] == u' ': self.commit_string(cond_letter_translate(u' ')) return True if key.mask & modifier.CONTROL_MASK + modifier.ALT_MASK: return False if key.mask & modifier.ALT_MASK: return False if (unichr(key.code) in self._valid_input_chars or self._editor._py_mode) and unichr(key.code) in u'abcdefghijklmnopqrstuvwxyz!@#$%': if self._auto_commit: pass res = self._editor.add_input(unichr(key.code)) if not res: sp_res = self._editor.space() if sp_res[0]: self.commit_string(sp_res[1] + key_char) self.add_string_len(sp_res[1]) self.db.check_phrase(sp_res[1], sp_res[2]) return True self.commit_string(key_char) return True res if self._auto_commit and self._editor.one_candidate(): pass self._update_ui() return True if key.code in (keysyms.equal, keysyms.Page_Down, keysyms.KP_Page_Down) and self._editor._candidates[0]: res = self._editor.page_down() self._update_lookup_table() return res if key.code in (keysyms.minus, keysyms.Page_Up, keysyms.KP_Page_Up) and self._editor._candidates[0]: res = self._editor.page_up() self._update_lookup_table() return res if key.code >= keysyms._1 and key.code <= keysyms._9 and self._editor._candidates[0]: input_keys = self._editor.get_all_input_strings() res = self._editor.number(key.code - keysyms._1) return True if key.code <= 127: self._editor.clear() return True return False def focus_in(self): if self._on: self.register_properties(self.properties) self._refresh_properties() self._update_ui() try: if self._sm_on: self._sm.Show() else: self._sm.Hide() def focus_out(self): try: self._sm.Hide() except: pass def enable(self): try: self._sm.Reset() except: pass self._on = True self.focus_in() def disable(self): self.reset() try: self._sm.Hide() except: pass self._on = False def lookup_table_page_up(self): if self._editor.page_up(): self._update_lookup_table() return True return True def lookup_table_page_down(self): if self._editor.page_down(): self._update_lookup_table() return True return False